﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using ZEntity.Data.Helper;

namespace ZEntity.Data
{
    public class BaseDB
    {
        public static SQLHelper DB {
            get { return SQLHelper.GetInstance(); }
        }

        public static void SetConn(string connString) {
            SQLHelper.SetConn(connString);
        }

        /// <summary>
        /// 按映射关系插入对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        protected static Guid Insert<T>(T obj) {
            object[] objs = typeof(T).GetCustomAttributes(true);
            return Guid.Empty;
        }

        /// <summary>
        /// 按映射关系更新对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        protected static void Update<T>(T obj) {

        }

        /// <summary>
        /// 按映射关系删除对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="PK">主键值</param>
        protected static void Delete<T>(object PK) {

        }

        /// <summary>
        /// 查询对象按主键（按映射关系获取对象）
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="PK">主键值</param>
        /// <returns>T对象</returns>
        protected static T QueryForObject<T>(object PK) where T : new() {
            string TableName = typeof(T).Name;
            System.Reflection.PropertyInfo[] infos = typeof(T).GetProperties();
            List<string> PropertyeList = new List<string>();
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append("SELECT ");
            string PrimaryKeyName = string.Empty;
            string PrimaryKeyType = string.Empty;
            foreach (System.Reflection.PropertyInfo info in infos) {
                PropertyeList.Add(info.Name);
                //if (info.IsDefined(typeof(ORMAttribute), false)) {
                //    PrimaryKeyName = info.Name;
                //    PrimaryKeyType = info.PropertyType.Name;
                //}
            }
            int listLength = PropertyeList.Count;
            for (int i = 0; i < listLength; i++) {
                sb.Append(i == listLength - 1 ? "[" + PropertyeList[i] + "]" : "[" + PropertyeList[i] + "]" + ",");
            }
            sb.Append(" FROM " + TableName);
            sb.AppendFormat(" WHERE " + PrimaryKeyName + "=" + (PrimaryKeyType == "Guid" ? "'" : "") + "{0}" + (PrimaryKeyType == "Guid" ? "'" : ""), PK);
            string sqls = sb.ToString();
            return QueryForObjectBySQL<T>(sqls);
        }

        /// <summary>
        /// 查询对象按SQL
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="sql">sql</param>
        /// <returns>T对象</returns>
        protected static T QueryForObjectBySQL<T>(string sql) where T : new() {
            DataTable dt = DB.ExecuteQuery(sql, CommandType.Text);
            dt.TableName = "Table1";
            T obj = default(T);
            if (dt.Rows.Count > 0) {
                obj = new T();
                System.Reflection.PropertyInfo info;
                foreach (DataColumn col in dt.Columns) {
                    if (col.ColumnName == "rowId")
                        continue;
                    info = obj.GetType().GetProperty(col.ColumnName);
                    info.SetValue(obj, DBTypeConvert(info.PropertyType.Name, dt.Rows[0][col.ColumnName]), null);
                }
            }
            return obj;
        }

        /// <summary>
        /// 查询对象集合按SQL
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="sql">sql</param>
        /// <returns>T对象List</returns>
        protected static IList<T> QueryForListBySQL<T>(string sql) where T : new() {
            DataTable dt = DB.ExecuteQuery(sql, CommandType.Text);
            dt.TableName = "Table1";
            return DataTableToList<T>(dt);
        }

        /// <summary>
        /// 转换DataTable为List
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="dt">dataTable对象</param>
        /// <returns>T对象List</returns>
        protected static IList<T> DataTableToList<T>(DataTable dt) where T : new() {
            IList<T> list = new List<T>();
            T obj;
            System.Reflection.PropertyInfo info;
            for (int i = 0; i < dt.Rows.Count; i++) {
                obj = new T();
                foreach (DataColumn col in dt.Columns) {
                    if (col.ColumnName == "rowId")
                        continue;
                    info = obj.GetType().GetProperty(col.ColumnName);
                    info.SetValue(obj, DBTypeConvert(info.PropertyType.Name, dt.Rows[i][col.ColumnName]), null);
                }
                list.Add(obj);
            }
            return list;
        }

        /// <summary>
        /// db类型转换
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="typeCode">类型代码</param>
        /// /// <param name="rawValue">源转换值</param>
        /// <returns>T类型</returns>
        private static object DBTypeConvert(string typeCode, object rawValue) {
            object rtn = new object();
            switch (typeCode) {
                case "Guid":
                    rtn = ConvertUtils.ToGuid(rawValue);
                    break;
                case "String":
                    rtn = ConvertUtils.ToString(rawValue);
                    break;
                case "Int32":
                    rtn = ConvertUtils.ToInt32(rawValue);
                    break;
                case "Boolean":
                    rtn = ConvertUtils.ToBoolean(rawValue);
                    break;
                case "DateTime":
                    rtn = ConvertUtils.ToDateTime(rawValue);
                    break;
            }
            return rtn;
        }                
    }
}
